package cn.wen233.client.service;

import cn.wen233.basic.model.Instance;
import cn.wen233.basic.model.Namespace;
import cn.wen233.basic.model.Service;
import cn.wen233.client.config.SunglowServerProperties;
import cn.wen233.client.net.HttpClient;
import cn.wen233.client.net.HttpMethod;
import cn.wen233.client.net.RestClient;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 服务端 Service包装
 *
 * @author wenei
 * @date 2021-10-25 19:44
 */
public class ClientCoreService {

    private static final ObjectMapper MAPPER = new ObjectMapper();


    private ClientCoreService() {
    }

    public static final String getServerPrefixUrl() {
        return HttpClient.getPrefix() + SunglowServerProperties.getIp() + ":" + SunglowServerProperties.getPort() + "/api/";
    }

    /**
     * 获取命名空间下的所有服务
     */
    public List<Service> getServices() {
        String url = getServerPrefixUrl() + PathConstants.SERVICES + SunglowServerProperties.getNamespaceId();
        return RestClient.requestForList(url, null, null, null, null, HttpMethod.GET, Service.class);
    }

    /**
     * 校验命名空间是否存在
     */
    public boolean existsNamespace(String namespaceId) {
        String url = getServerPrefixUrl() + PathConstants.NAMESPACES + namespaceId;
        Namespace namespace = RestClient
                .requestForObject(url, null, null, null, null, HttpMethod.GET, Namespace.class);
        return namespace != null;
    }

    /**
     * 查询命名空间下的指定服务的所有节点实例
     */
    public List<Instance> getAllInstance(String namespaceId, String serviceId) {
        String url = getServerPrefixUrl() + PathConstants.INSTANCES;
        Map<String, String> params = new HashMap<>();
        params.put("namespaceId", namespaceId);
        params.put("serviceId", serviceId);
        return RestClient.requestForList(url, null, params, null, null, HttpMethod.GET, Instance.class);
    }

    /**
     * 查询命名空间下的分组的指定服务
     */
    public Service getService(String namespaceId, String groupName, String serviceName) {
        String url = getServerPrefixUrl() + PathConstants.SERVICES + namespaceId + '/' + groupName;
        Map<String, String> params = new HashMap<>();
        params.put("serviceName", serviceName);
        return RestClient.requestForObject(url, null, params, null, null, HttpMethod.GET, Service.class);
    }

    /**
     * 注册服务
     */
    public boolean registerService(String namespaceId, String groupName, String serviceName, String appName) {
        String url = getServerPrefixUrl() + PathConstants.SERVICES;
        Map<String, String> params = new HashMap<>();
        params.put("name", serviceName);
        params.put("appName", appName);
        params.put("groupName", groupName);
        params.put("namespaceId", namespaceId);
        RestClient.requestForObject(url, null, params, null, null, HttpMethod.POST, Object.class);
        return true;
    }

    /**
     * 为服务注册节点
     * 返回instance id
     */
    public Instance registerInstance(String namespaceId, String serviceId, String host, int port) {
        String url = getServerPrefixUrl() + PathConstants.INSTANCES;
        Map<String, String> params = new HashMap<>();
        params.put("namespaceId", namespaceId);
        params.put("serviceId", serviceId);
        params.put("host", host);
        params.put("port", String.valueOf(port));
        return RestClient.requestForObject(url, null, params, null, null, HttpMethod.POST, Instance.class);
    }

    public void insertServiceRecord(String namespaceId, String groupName, String serviceName) {
        String url = getServerPrefixUrl() + PathConstants.SERVICE_RECORD;
        Map<String, String> params = new HashMap<>();
        params.put("namespace", namespaceId);
        params.put("groupName", groupName);
        params.put("serviceName", serviceName);
        RestClient.requestForObject(url, null, null, MAPPER.convertValue(params, JsonNode.class).toString(), null, HttpMethod.POST, Object.class);
    }

    public void insertInstanceRecord(String namespaceId, String groupName, String serviceName, String ip, int port) {
        String url = getServerPrefixUrl() + PathConstants.INSTANCE_RECORD;
        Map<String, String> params = new HashMap<>();
        params.put("namespace", namespaceId);
        params.put("groupName", groupName);
        params.put("serviceName", serviceName);
        params.put("ip", ip);
        params.put("port", String.valueOf(port));
        RestClient.requestForObject(url, null, null, MAPPER.convertValue(params, JsonNode.class).toString(), null, HttpMethod.POST, Object.class);
    }

    public void instanceHeartbeat(String instanceId) {
        String url = getServerPrefixUrl() + PathConstants.INSTANCE_HEARTBEAT;
        Map<String, String> params = new HashMap<>();
        params.put("instanceId", instanceId);
        RestClient.requestForObject(url, null, params, null, null, HttpMethod.GET, Object.class);
    }

    private static volatile ClientCoreService INSTANCE = null;

    public static ClientCoreService getInstance() {
        if (INSTANCE == null) {
            synchronized (ClientCoreService.class) {
                if (INSTANCE == null) {
                    INSTANCE = new ClientCoreService();
                }
            }
        }
        return INSTANCE;
    }

    public static void main(String[] args) {
//        System.out.println(getInstance().getService("public", "default", "Service11"));
//        System.out.println(getInstance().registerService("public", "default", "Service11", "testApp"));
//        System.out.println(getInstance().registerInstance("public", "2951635704414732288", "localhost", 1999));
//        System.out.println(getInstance().getInstances("public", "Service1"));
//        System.out.println(getInstance().existsNamespace("public"));
        getInstance().insertServiceRecord("public", "default", "test");
        System.out.println();
    }
}
